package process

import (
	"encoding/json"
	"fmt"
	"net"
	"retalk/common/message"
	"retalk/server/model"
	"retalk/server/utils"
)

type UserProcess struct {
	Conn   net.Conn //连接
	UserId int
}

//处理用户登录请求
func (this *UserProcess) ServerProcessLogin(mes *message.Message) (err error) {
	//1. 从mes中去除mes.Data,并反序列化成LoginMes
	var loginMes message.LoginMes
	err = json.Unmarshal([]byte(mes.Data), &loginMes)
	if err != nil {
		fmt.Println("处理用户登录请求时 json.Unmarshal 错误 err=", err)
		return
	}

	//2. 设置返回消息
	var resMes message.Message
	resMes.Type = message.LoginResMesType
	var loginResMes message.LoginResMes

	//到数据库中完成用户名和密码对比
	user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)
	if err != nil { //登录失败
		if err == model.ERROR_USER_NOTEXISTS {
			loginResMes.Code = 500
			loginResMes.Error = err.Error()
		} else if err == model.ERROR_USER_PWD {
			loginResMes.Code = 403
			loginResMes.Error = err.Error()
		} else {
			loginResMes.Code = 505
			loginResMes.Error = "服务器内部错误"
		}
		fmt.Println("登录失败:", loginResMes.Error)
	} else { //登录成功
		loginResMes.Code = 200
		//将登录成功的用户ID设置到当前UserProcess中
		this.UserId = loginMes.UserId
		//用户登录成功时，把登录成功的用户放到userMgr中
		userMgr.AddOnlineUser(this)
		//通知其他用户自己已上线
		this.NotifyOthersOnLineUsers(loginMes.UserId)
		//将当前在线用户的id放到LoginResMes.UserIds
		for id, _ := range userMgr.onlineUsers {
			loginResMes.UserIds = append(loginResMes.UserIds, id)
		}
		fmt.Println("user登录成功:", user)
	}

	//3. 将返回消息序列化
	data, err := json.Marshal(loginResMes)
	if err != nil {
		fmt.Println("处理用户登录请求时 json.Marshal 错误，err=", err)
		return
	}

	//4. 将data赋值给resMes并序列化
	resMes.Data = string(data)
	data, err = json.Marshal(resMes)
	if err != nil {
		fmt.Println("处理用户登录请求时 json.Marshal 错误，err=", err)
		return
	}

	//5.发送消息
	transfer := &utils.Transfer{
		Conn: this.Conn,
	}
	transfer.WritePkg([]byte(data))
	return
}

//处理用户注册请求
func (this *UserProcess) ServerProcessRegister(mes *message.Message) (err error) {
	//1. 从mes中去除mes.Data,并反序列化成LoginMes
	var registerMes message.RegisterMes
	err = json.Unmarshal([]byte(mes.Data), &registerMes)
	if err != nil {
		fmt.Println("处理用户注册请求时 json.Unmarshal 错误 err=", err)
		return
	}

	//2. 设置返回消息
	var resMes message.Message
	resMes.Type = message.RegisterResMesType
	var registerResMes message.RegisterResMes

	//到数据库确定是否可以注册
	err = model.MyUserDao.Register(&registerMes.User)
	if err != nil {
		if err == model.ERROR_USER_EXISTS {
			registerResMes.Code = 505
			registerResMes.Error = model.ERROR_USER_EXISTS.Error()
		} else {
			registerResMes.Code = 506
			registerResMes.Error = "注册时发生未知错误..."
		}
	} else {
		registerResMes.Code = 200
		fmt.Printf("用户 %v  注册成功！\n", registerMes.User.UserId)
	}

	//3. 将返回消息序列化
	data, err := json.Marshal(registerResMes)
	if err != nil {
		fmt.Println("处理用户注册请求时 json.Marshal 错误，err=", err)
		return
	}

	//4. 将data赋值给resMes并序列化
	resMes.Data = string(data)
	data, err = json.Marshal(resMes)
	if err != nil {
		fmt.Println("处理用户注册请求时 json.Marshal 错误，err=", err)
		return
	}

	//5.发送消息
	transfer := &utils.Transfer{
		Conn: this.Conn,
	}
	transfer.WritePkg([]byte(data))
	return
}

//通知所有在线用户
func (this *UserProcess) NotifyOthersOnLineUsers(userid int) {
	//遍历onlineUsers,并逐个发送NotifyUserStatus
	for id, userProcess := range userMgr.onlineUsers {
		if id == userid { //过滤掉自己
			continue
		}
		//开始通知
		userProcess.NotifyMeOnline(userid)
	}
}

//发送我上线的消息
func (this *UserProcess) NotifyMeOnline(userid int) {
	var mes message.Message
	mes.Type = message.NotifyUserStatusType

	var notifyUserStatus message.NotifyUserStatusMes
	notifyUserStatus.UserId = userid
	notifyUserStatus.Status = message.UserOnline
	data, err := json.Marshal(notifyUserStatus)
	if err != nil {
		fmt.Println("发送我上线的消息时 json.Marshal 发生错误,err=", err)
		return
	}

	//设置消息内容
	mes.Data = string(data)
	data, err = json.Marshal(mes)
	if err != nil {
		fmt.Println("发送我上线的消息时 json.Marshal 发生错误,err=", err)
		return
	}

	//发送消息
	transfer := &utils.Transfer{
		Conn: this.Conn,
	}
	err = transfer.WritePkg(data)
	if err != nil {
		fmt.Println("发送我上线的消息时 transfer.WritePkg 发生错误,err=", err)
		return
	}
}
